package com.gui;

import com.exceptions.DebugException;
import com.gooddies.wiring.annotations.PostWiring;
import com.gooddies.wiring.annotations.Wire;
import com.gooddies.wiring.annotations.WiringComponent;
import com.gui.interfaces.HighlightableNotEditable;
import com.gui.interfaces.StatusTextManipulator;
import com.peg.dataobjects.Context;
import com.peg.events.DebugEvent;
import com.peg.rules.Rule;
import java.awt.Color;

/**
 * @author sad
 */
@WiringComponent(singleton = false)
public class Debugger {

    @Wire(value = "GrammarEditor")
    private HighlightableNotEditable sourceField;
    @Wire(value = "DataEditor")
    private HighlightableNotEditable dataField;
    @Wire(value = "MainFrame")
    private StatusTextManipulator status;
    private final String DEBUG_LINE = "debugLine";
    @Wire
    private ParsingContext parsingContext;
    private boolean stop = true;
    private boolean stepFlag = false;
    @Wire
    private Breakpoints breakpoints;

    @Wire
    private LineNumberCalculator lineNumberCalculator;

    @PostWiring
    private void init() {
        Rule.setDebugEvent(new DebugEvent() {
            @Override
            public void debugEvent(Rule rule, Context context) {
                int start = rule.getStart();
                int lineNumber = lineNumberCalculator.computeLineNumber(start);
                if (checkIsBreakPoint(lineNumber)) {
                    stepFlag = false;
                    onRule(rule, context);
                    while (stop) {
                        sleep();
                    }
                    stop = true;
                }
            }
        });
    }

    public void setStepFlag(boolean stepFlag) {
        this.stepFlag = stepFlag;
    }

    private boolean checkIsBreakPoint(int lineNumber) {
        return stepFlag == true || breakpoints.hasBreakpoint(lineNumber);
    }

    private void sleep() {
        try {
            Thread.sleep(10);
        } catch (InterruptedException ex) {
            throw new RuntimeException(ex);
        }
    }

    private void onRule(Rule rule, Context context) {
        int offset = rule.getStart();
        int length = rule.getLength();
        sourceField.highlight(DEBUG_LINE, offset, length, Color.yellow);
        status.setStatusText(rule.toString());
    }

    public void closeSession() {
        sourceField.removeHighlight(DEBUG_LINE);
        dataField.removeHighlight(DEBUG_LINE);
        Rule.setDebugEvent(null);
    }

    public void step() {
        if (parsingContext.getBaseParser() == null) {
            throw new DebugException("There are errors in parser");
        }
        stop = false;
        stepFlag = true;
    }

    public void run() {
        if (parsingContext.getBaseParser() == null) {
            throw new DebugException("There are errors in parser");
        }
        stop = false;
        stepFlag = false;
    }
}
